/*
 * @(#)BaseDaoImpl.java  
 *       
 * 系统名称：    OpenSeats信息系统
 * 版本号：      1.0
 *  
 * Copyright (c)  TravelSky.com
 * All rights reserved.
 * 
 * 作者: 	  yurb
 * 创建日期:    2008-10-5
 * 
 * 功能描述：
 * 公用方法描述：
 * 
 * 修改人：
 * 修改日期：
 * 修改原因：
 * 
 */
package com.bjypc.youth.dao;

import java.lang.reflect.ParameterizedType;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.Set;

import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import javax.persistence.Query;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import com.bjypc.youth.common.PageResult;
import com.bjypc.youth.common.QueryCriteria;
import com.bjypc.youth.entity.EntityBase;
import com.bjypc.youth.entity.RemoveMarkedEntityBase;

/**
 * 
 * <p>
 * Dao基类实现<br>
 * 
 * @author yurb
 * @since 2008-10-5 下午02:11:53
 */
@SuppressWarnings("unchecked")
public class BaseDaoImpl<T extends EntityBase> implements IDao<T>
{

	@PersistenceContext(unitName = "bjyouth")
	private EntityManager em;

	protected final Log log = LogFactory.getLog(getClass());

	private Class<T> entityClass;

	public BaseDaoImpl()
	{
		this.entityClass = (Class<T>) ((ParameterizedType) getClass()
				.getGenericSuperclass()).getActualTypeArguments()[0];
	}
    @PersistenceContext
    public void setEntityManager(EntityManager em) {
        this.em = em;
    }
    private EntityManager getEntityManager() {
        return em;
    }    
	public Class<T> getEntityBeanType()
	{
		return entityClass;
	}

	/**
	 * 删除数据模型
	 */
	public void remove(T o)
	{
		removeEntity(o);
	}

	/**
	 * 根据id删除数据模型，类当前Dao可自动识别
	 */
	public void removeById(Long id)
	{
		removeEntity(findById(id));
	}

	/**
	 * 根据id和类删除当前Dao
	 */
	public void removeById(Class clazz, Long id)
	{
		removeEntity(findById(clazz, id));
	}

	/**
	 * 保存当前对象
	 */
	public void save(T o)
	{
		saveEntity(o, null);
	}

	/**
	 * 修改当前对象
	 */
	public void update(T o)
	{
		updateEntity(o, null);
	}

	/**
	 * 
	 * 
	 * @param o
	 * @param createDate
	 *            <li>TODO 输入参数的说明,如集合的元素类型,是否允许空等 <li>TODO
	 *            返回结果的说明,如返回集合的元素类型,返回结果代表的含义 <li>TODO 异常的说明,如抛出什么异常,代表的含义
	 */
	private void saveEntity(EntityBase o, Date createDate)
	{
		em.persist(o);
	}

	/**
	 * 
	 * 
	 * @param obj
	 *            <li>TODO 输入参数的说明,如集合的元素类型,是否允许空等 <li>TODO
	 *            返回结果的说明,如返回集合的元素类型,返回结果代表的含义 <li>TODO 异常的说明,如抛出什么异常,代表的含义
	 */
	private void removeEntity(EntityBase obj)
	{
		if (obj instanceof RemoveMarkedEntityBase)
		{
			RemoveMarkedEntityBase entity = (RemoveMarkedEntityBase) obj;
			entity.setDeleted(true);
			updateEntity(entity, new Date());
		} else
			em.remove(obj);
	}

	/**
	 * 
	 * 内置审计功能的修改
	 * 
	 * @param o
	 * @param updateDate
	 *            <li>TODO 输入参数的说明,如集合的元素类型,是否允许空等 <li>TODO
	 *            返回结果的说明,如返回集合的元素类型,返回结果代表的含义 <li>TODO 异常的说明,如抛出什么异常,代表的含义
	 */
	private void updateEntity(EntityBase o, Date updateDate)
	{


		em.merge(o);

	}

	/**
	 * 根据id查找当前对象(类型Dao内置)
	 */
	public T findById(Long id)
	{
		return em.find(entityClass, id);
	}

	/**
	 * 根据id和类型查找当前对象
	 */
	public T findById(Class clazz, Long id)
	{
		return em.find(entityClass, id);
	}

	public List<T> findAll()
	{
		return em.createQuery("from " + getEntityBeanType().getName())
				.getResultList();
	}

	/**
	 * 与数据库同步当前EntityManager中的对象
	 */
	public void flush()
	{
		em.flush();
	}

	/**
	 * 
	 * 清楚当前EntityManager中的对象
	 */
	public void clear()
	{
		em.clear();
	}

	/**
	 * 根据条件，替换参数对jpaql进行查询
	 * 
	 * @param jpaql
	 *            查询语句
	 * @param paramValues
	 *            可变数量的查询参数
	 */
	public List find(String jpaql, Object... paramValues)
	{
		Query query = em.createQuery(jpaql);
		if (paramValues != null && paramValues.length > 0)
		{
			for (int i = 0; i < paramValues.length; i++)
			{
				query.setParameter(i+1, paramValues[i]);
			}
		}
		return query.getResultList();
	}

	/**
	 * 根据条件，替换参数对jpaql进行查询
	 * 
	 * @param jpaql
	 *            查询语句
	 * @param paramValueList
	 *            查询参数
	 */
	public List find(String jpaql, List paramValueList)
	{
		Query query = em.createQuery(jpaql);
		if (paramValueList != null && paramValueList.size() > 0)
		{
			for (int i = 0; paramValueList != null && i < paramValueList.size(); i++)
			{
				query.setParameter(i + 1, (String)paramValueList.get(i));
			}
		}

		return query.getResultList();
	}

	/**
	 * 根据条件，替换参数对命名的jpaql进行查询
	 * 
	 * @param queryName
	 *            查询语句的名称
	 * @param paramValues
	 *            查询参数
	 */
	public List namedQuery(String queryName, Object... paramValues)
	{
		Query query = em.createNamedQuery(queryName);
		if (paramValues != null && paramValues.length > 0)
		{
			for (int i = 0; i < paramValues.length; i++)
			{
				query.setParameter(i, paramValues[i]);
			}
		}
		return query.getResultList();
	}

	/**
	 * 根据条件，替换参数对命名的jpaql进行查询
	 * 
	 * @param queryName
	 *            查询语句的名称
	 * @param paramValueList
	 *            查询参数
	 */
	public List namedQuery(String queryName, List paramValueList)
	{
		Query query = em.createNamedQuery(queryName);
		if (paramValueList != null && paramValueList.size() > 0)
		{
			for (int i = 0; paramValueList != null && i < paramValueList.size(); i++)
			{
				query.setParameter(i, paramValueList.get(i));
			}
		}
		return query.getResultList();
	}

	/**
	 * 根据条件，替换参数对native sql语句进行查询
	 * 
	 * @param sql
	 *            查询语句
	 * @param paramValues
	 *            查询参数
	 */

	public List nativeQuery(String sql, Object... paramValues)
	{
		Query query = em.createNativeQuery(sql);
		if (paramValues != null && paramValues.length > 0)
		{
			for (int i = 0; i < paramValues.length; i++)
			{
				query.setParameter(i, paramValues[i]);
			}
		}
		return query.getResultList();
	}

	/**
	 * 根据条件，替换参数对native sql语句进行查询
	 * 
	 * @param sql
	 *            查询语句
	 * @param paramValueList
	 *            查询参数
	 */
	public List nativeQuery(String sql, List paramValueList)
	{
		Query query = em.createNativeQuery(sql);
		if (paramValueList != null && paramValueList.size() > 0)
		{
			for (int i = 0; paramValueList != null && i < paramValueList.size(); i++)
			{
				query.setParameter(i, paramValueList.get(i));
			}
		}
		return query.getResultList();
	}

	/**
	 * 按照条件进行翻页查询
	 * 
	 * @param jpaql
	 *            查询语句
	 * @param criteria
	 *            翻页条件
	 * @return 当前页面的内容
	 */
	public PageResult query(String jpaql, QueryCriteria criteria)
	{
		Query query = em.createQuery(jpaql);

		query.setFirstResult(criteria.getCurrentIndex());
		query.setMaxResults(criteria.getPageSize());

		Set<Map.Entry<String, Object>> entrySet = criteria.getQueryCondition()
				.entrySet();
		for (Map.Entry<String, Object> entry : entrySet)
		{
			query.setParameter(entry.getKey(), entry.getValue());
		}
		List contentList = query.getResultList();

		String countSql = DaoUtil.getCountQL(jpaql);
		Query countQuery = em.createQuery(countSql);
		Set<Map.Entry<String, Object>> countEntrySet = criteria
				.getQueryCondition().entrySet();
		for (Map.Entry<String, Object> entry : countEntrySet)
		{
			countQuery.setParameter(entry.getKey(), entry.getValue());
		}
		Long count = (Long) countQuery.getSingleResult();

		PageResult result = new PageResult();
		result.setContent(contentList);
		result.setCurrentIndex(criteria.getCurrentIndex());
		result.setCountPage((count.intValue() + criteria.getPageSize() - 1)
				/ criteria.getPageSize());
		result.setTotalCount(count.intValue());
		return result;
	}
}
